package at.fhj.swd.pse.entities;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import org.hibernate.annotations.Index;

@Entity
@Table(name = "users")
public class User implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id", updatable = false, nullable = false)
	private int id;

	@NotNull
	private String password; // SHA1 -> http://www.sha1generator.de/

	@NotNull
	@Index(name = "IX_users_username")
	private String username;

	@Column(nullable = false, columnDefinition = "boolean default false")
	private boolean admin;

	/* User Profile Data */
	private String firstName;
	private String lastName;
	private String email;
	private String address;
	private int roomNumber;
	private String city;
	private Department department;
	private Status userStatus;
	@Lob
	private byte[] image;
	private String telephone;
	private String interests;
	private String expertise;

	@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinTable(name = "UserFriends", joinColumns = @JoinColumn(name = "User_ID"), inverseJoinColumns = @JoinColumn(name = "Friend_ID"))
	private Set<User> friends = new HashSet<User>();

	public User() {
		super();
	}

	public int getId() {
		return this.id;
	}

	public void setId(final int id) {
		this.id = id;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(final String password) {
		this.password = password;
	}

	public String getUsername() {
		return this.username;
	}

	public void setUsername(final String username) {
		this.username = username;
	}

	public boolean isAdmin() {
		return this.admin;
	}

	public void setAdmin(final boolean admin) {
		this.admin = admin;
	}

	public String getFirstName() {
		return this.firstName;
	}

	public void setFirstName(final String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return this.lastName;
	}

	public void setLastName(final String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return this.email;
	}

	public void setEmail(final String email) {
		this.email = email;
	}

	public String getAddress() {
		return this.address;
	}

	public void setAddress(final String address) {
		this.address = address;
	}

	public int getRoomNumber() {
		return this.roomNumber;
	}

	public void setRoomNumber(final int roomNumber) {
		this.roomNumber = roomNumber;
	}

	public String getCity() {
		return this.city;
	}

	public void setCity(final String city) {
		this.city = city;
	}

	public Department getDepartment() {
		return this.department;
	}

	public void setDepartment(final Department department) {
		this.department = department;
	}

	public Status getUserStatus() {
		return this.userStatus;
	}

	public void setUserStatus(final Status userStatus) {
		this.userStatus = userStatus;
	}

	public String getTelephone() {
		return this.telephone;
	}

	public void setTelephone(final String telephone) {
		this.telephone = telephone;
	}

	public String getInterests() {
		return this.interests;
	}

	public void setInterests(final String interests) {
		this.interests = interests;
	}

	public String getExpertise() {
		return this.expertise;
	}

	public void setExpertise(final String expertise) {
		this.expertise = expertise;
	}

	public byte[] getImage() {
		return this.image;
	}

	public void setImage(final byte[] image) {
		this.image = image;
	}

	public Set<User> getFriends() {
		return this.friends;
	}

	public void setFriends(final Set<User> friends) {
		this.friends = friends;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = (prime * result) + this.id;
		result = (prime * result) + ((this.username == null) ? 0 : this.username.hashCode());
		return result;
	}

	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (this.getClass() != obj.getClass()) {
			return false;
		}
		User other = (User) obj;
		if (this.id != other.id) {
			return false;
		}
		if (this.username == null) {
			if (other.username != null) {
				return false;
			}
		} else if (!this.username.equals(other.username)) {
			return false;
		}
		return true;
	}

}
